package com.sigmazero13.bgjeeves.utils;

import java.util.ArrayList;
import java.util.List;

import com.sigmazero13.bgjeeves.model.GamePlayInfo;
import com.sigmazero13.bgjeeves.model.GamePlayerInfo;
import com.sigmazero13.bgjeeves.model.PlayReport;

public class PlayReportBuilder {

	public static enum ReportVariable {
		PLAYER("Player Name"),
		TEAM("Team"),
		NUMPLAYERS("Number of Players");
		
		private String typeName;
		
		private ReportVariable(String typeName) {
			this.typeName = typeName;
		}
		
		public String getTypeName() {
			return typeName;
		}
		
		@Override
		public String toString() {
			return typeName;
		}
		
		public static ReportVariable getReportAxisType(int ord) {
			for (ReportVariable rt : ReportVariable.values()) {
				if (ord == rt.ordinal())
					return rt;
			}
			return null;
		}
	}
	
	private List<GamePlayInfo> plays;
	
	public PlayReportBuilder(List<GamePlayInfo> plays) {
		this.plays = plays;
	}
	
	public void setPlays(List<GamePlayInfo> plays) {
		this.plays = plays;
	}
	
	public List<GamePlayInfo> getPlays() {
		return plays;
	}
	
	public static boolean isValidReportType(ReportVariable rowType, ReportVariable colType) {
		// if either is null, invalid
		if (rowType == null || colType == null) 
			return false;
		
		// if both row and column are Number of Players, invalid
		if (rowType.equals(colType) && rowType.equals(ReportVariable.NUMPLAYERS))
			return false;
		
		// All other combos are valid
		return true;
	}
	
	public PlayReport buildReport(ReportVariable rowType, ReportVariable colType) {
		PlayReport report = new PlayReport();
		
		if (rowType == null || colType == null) {
			throw new IllegalArgumentException("Invalid Report Type!");
		}
		
		for (GamePlayInfo play : plays) {
			buildPlay(report, rowType, colType, play);
		}
		
		return report;
	}
	
	private String getKey(ReportVariable keyType, GamePlayerInfo player, Integer numPlayers) {
		switch (keyType) {
		case PLAYER:
			return player.getName();
		case TEAM:
			List<String> teams = player.getTeams();
			if (teams != null) {
				return teams.get(0);
			} else {
				return null;
			}
		case NUMPLAYERS:
			return numPlayers + " pl.";
		default:
			return "";
		}
	}
	
	private void buildPlay(PlayReport report, ReportVariable rowType, ReportVariable colType, GamePlayInfo play) {
		Integer numPlayers = play.getNumPlayers();
		
		boolean rowColMatch = rowType.equals(colType);
		
		for (GamePlayerInfo player : play.getPlayers()) {
			String rowKey = getKey(rowType, player, numPlayers);
			
			List<String> colKeys = new ArrayList<String>();
			if (rowColMatch) {
				for (GamePlayerInfo otherPlayer : play.getPlayers()) {
					if (player == otherPlayer) continue;
					
					colKeys.add(getKey(colType, otherPlayer, numPlayers));
				}
			} else {
				colKeys.add(getKey(colType, player, numPlayers));
			}
			
			boolean countedTotals = false;
			for (String colKey : colKeys) {
				boolean win = player.getWinner();
				
				report.addResult(rowKey, colKey, win);
				
				if (rowColMatch && countedTotals) continue;
				
				countedTotals = true;
				if (!colType.equals(ReportVariable.NUMPLAYERS))
					report.addResult("TOTAL", colKey, win);
				if (!rowType.equals(ReportVariable.NUMPLAYERS))
					report.addResult(rowKey, "TOTAL", win);
			}	
		}
	}
}
